cmake_minimum_required (VERSION 3.1)

project(reksio)

enable_language(C ASM ASM_MASM)

include(ExternalProject)

option(CERN_BUILD "Enables CERN-specific settings" OFF)

add_compile_options($<$<CXX_COMPILER_ID:MSVC>:/MP>)

# for breakpad
add_definitions(-DUNICODE)

# store commit ID (branch_sha)
if (COMMIT_ID)
    add_definitions(-DCOMMIT_ID="${COMMIT_ID}")
else(COMMIT_ID)
    add_definitions(-DCOMMIT_ID="custom-build")
endif(COMMIT_ID)

# store Reksio version
if (REKSIO_VERSION)
    add_definitions(-DREKSIO_VERSION="v${REKSIO_VERSION}")
else(REKSIO_VERSION)
    add_definitions(-DREKSIO_VERSION="test")
endif(REKSIO_VERSION)

# store versions of python package dependiencies
if (PYCHEBY_VERSION)
    add_definitions(-DPYCHEBY_VERSION="v${PYCHEBY_VERSION}")
else(PYCHEBY_VERSION)
    add_definitions(-DPYCHEBY_VERSION="NOT_DEFINED")
endif(PYCHEBY_VERSION)

if (CHEBY_VERSION)
    add_definitions(-DCHEBY_VERSION="v${CHEBY_VERSION}")
else(CHEBY_VERSION)
    add_definitions(-DCHEBY_VERSION="NOT_DEFINED")
endif(CHEBY_VERSION)

if (CODE_GEN_VERSION)
    add_definitions(-DCODE_GEN_VERSION="v${CODE_GEN_VERSION}")
else(CODE_GEN_VERSION)
    add_definitions(-DCODE_GEN_VERSION="NOT_DEFINED")
endif(CODE_GEN_VERSION)

# Find includes in corresponding build directories
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Instruct CMake to run moc automatically when needed
set(CMAKE_AUTOMOC ON)
# Create code from a list of Qt designer ui files
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)

set(CMAKE_CXX_FLAGS_RELEASE "-O2")

if (MSVC)
    set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD /Zi")
    set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd /Zi")
    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /INCREMENTAL:NO /MAP /Debug /opt:ref")
endif (MSVC)

if (UNIX)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -Wall -Wextra -g3 -ggdb")
	set(CMAKE_ASM_FLAGS "${CFLAGS} -x assembler-with-cpp")
endif (UNIX)

# cpp standard
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(Qt5 COMPONENTS Core Widgets Gui REQUIRED)

add_subdirectory(pybind11)

ExternalProject_Add(
        yaml_cpp_project
        SOURCE_DIR "${CMAKE_SOURCE_DIR}/yaml-cpp/"
        INSTALL_DIR "${CMAKE_BINARY_DIR}/prefix"
        CMAKE_ARGS -DYAML_CPP_BUILD_TESTS=OFF -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
)

include_directories(SYSTEM "${PROJECT_BINARY_DIR}/prefix/include")


# breakpad
set(BREAKPAD_SOURCE_DIR "${PROJECT_SOURCE_DIR}/breakpad/breakpad")
set(BREAKPAD_INCLUDE_DIR "${BREAKPAD_SOURCE_DIR}/src")

add_subdirectory(breakpad)

# build date
string(TIMESTAMP TODAY "%Y.%m.%d.%H.%M")

add_definitions(-DTODAY="${TODAY}")

# crash handler
add_subdirectory(crash_handler)

add_definitions(-DQT_NO_KEYWORDS) # to use python


list (APPEND RESOURCES src/resources.qrc)

qt5_add_resources (RCC_SOURCES ${RESOURCES})

SET(UIS
    src/mainwindow.ui
    src/searchwindow.ui
    src/texteditform.ui
    src/settingsdialog.ui)


SET(SOURCES
    src/pythoninterpreterlineedit.cpp
    src/customexceptionhandler.cpp
    src/utils.cpp
    src/filewatcher.cpp
    src/settingsdialog.cpp
    src/memory_node_yaml.cpp
    src/attributecontainervalidator.cpp
    src/attributevalidator.cpp
    src/texteditform.cpp
    src/validatornode.cpp
    src/attributecontainer.cpp
    src/searchwindow.cpp
    src/treenodeoverviewmodel.cpp
    src/pythonmodules.cpp
    src/pythonaction.cpp
    src/consolestream.cpp
    src/python_mappings.cpp
    src/main.cpp
    src/mainwindow.cpp
    src/memorynode.cpp
    src/attribute.cpp
    src/validator.cpp
    src/nodesmodel.cpp
    src/attributesmodel.cpp
    src/pythonvalidator.cpp
    src/attributesviewdelegate.cpp
    src/commands.cpp
    src/customnodesview.cpp
    src/customattributesview.cpp
)

# copy files
file(GLOB PYTHON_SCRIPTS "${CMAKE_CURRENT_SOURCE_DIR}/python_scripts/*.py")
foreach(in_python_file ${PYTHON_SCRIPTS})
    get_filename_component(out_python_file ${in_python_file} NAME)
    configure_file(${in_python_file} "${CMAKE_CURRENT_BINARY_DIR}/python_scripts/${out_python_file}" COPYONLY)
endforeach()

if (CERN_BUILD)
    configure_file("${CMAKE_CURRENT_SOURCE_DIR}/settings/settings.json.cern" "${CMAKE_CURRENT_BINARY_DIR}/settings/settings.json" COPYONLY)
    add_definitions(-DCERN_BUILD)
else (CERN_BUILD)
    configure_file("${CMAKE_CURRENT_SOURCE_DIR}/settings/settings.json" "${CMAKE_CURRENT_BINARY_DIR}/settings/settings.json" COPYONLY)
endif (CERN_BUILD)

configure_file("${CMAKE_CURRENT_SOURCE_DIR}/schema/schema.yaml" "${CMAKE_CURRENT_BINARY_DIR}/schema/schema.yaml" COPYONLY)

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)
add_executable(reksio WIN32 ${SOURCES} ${RCC_SOURCES} ${UIS})

add_dependencies(reksio yaml_cpp_project)

target_link_libraries(reksio ${Qt5Widgets_LIBRARIES} ${Qt5Gui_LIBRARIES} ${Qt5Core_LIBRARIES} pybind11::embed breakpad_client)
if (MSVC)
    target_link_libraries(reksio optimized "${CMAKE_BINARY_DIR}/prefix/lib/libyaml-cppmd.lib")
    target_link_libraries(reksio debug "${CMAKE_BINARY_DIR}/prefix/lib/libyaml-cppmdd.lib")
else (MSVC)
    # pthread for breakpad
    set(THREADS_PREFER_PTHREAD_FLAG ON)
    find_package(Threads REQUIRED)
    target_link_libraries(reksio "${CMAKE_BINARY_DIR}/prefix/lib/libyaml-cpp.a" Threads::Threads)
endif (MSVC)

target_include_directories(reksio PUBLIC ${Qt5Gui_INCLUDE_DIRS} ${Qt5Widgets_INCLUDE_DIRS} ${Qt5Core_INCLUDE_DIRS} ${BREAKPAD_INCLUDE_DIR})
target_link_libraries(reksio Qt5::Core Qt5::Gui Qt5::Widgets)
